const axios = require('axios')
const path = require('path')
const webpack = require('webpack')
const memoryFs = require('memory-fs')
const proxy = require('http-proxy-middleware')
const serverConfig = require('../../build/webpack.config.server')
const ReactDomServer = require('react-dom/server')

// 通过请求获取模板
const getTemplate = () => {
  return new Promise((resolve, reject) => {
    axios.get('http://localhost:8888/public/index.html')
      .then(res => {
        resolve(res.data)
      })
      .catch(reject)
  })
}


const NativeModule = require('module')
const vm = require('vm')

// `(function(exports, require, module, __finename, __dirname){ ...bundle code })`
const getModuleFromString = (bundle, filename) => {
  const m = { exports: {} }
  const wrapper = NativeModule.wrap(bundle)
  const script = new vm.Script(wrapper, {
    filename: filename,
    displayErrors: true,
  })
  const result = script.runInThisContext()
  result.call(m.exports, m.exports, require, m)
  return m
}


const Module = module.constructor

const mfs = new memoryFs

const serverCompiler = webpack(serverConfig)
serverCompiler.outputFileSystem = mfs // 输出到内存中
let serverBundle
// 监听配置文件
serverCompiler.watch({}, (err, stats) => {
  if (err) throw err
  stats = stats.toJson()   // 打包时候输出的信息
  stats.errors.forEach(err => {
    console.error(err)
  })
  stats.warnings.forEach(warn => {
    console.warn(warn)
  })

  const bundlePath = path.join(
    serverConfig.output.path,
    serverConfig.output.filename
  )

  
  // 从内存中读取出来（string）
  // const bundle = mfs.readFileSync(bundlePath, 'utf-8')
  // const m = new Module() // 用Module解析字符串
  // m._compile(bundle, 'server-entry.js') // 指定文件名称
  // serverBundle = m.default

  const bundle = mfs.readFileSync(bundlePath, 'utf-8')
  const m = getModuleFromString(bundle, 'server-entry.js')
  serverBundle = m.exports.default
})

module.exports = function(app) {

  // 代理
  app.use('/public', proxy({
    target: 'http://localhost:8888'
  }))

  app.get('*', (req, res) => {
    getTemplate().then(template => {
      const content = ReactDomServer.renderToString(serverBundle)
      res.send(template.replace('<app></app>', content))
    },err => {
      console.error(err)
    })
  })
}